﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using SingleUserMall.Authorization.Users;
using SingleUserMall.Common;
using SingleUserMall.Coupons;
using SingleUserMall.Orders.Form;
using SingleUserMall.Orders.VO;
using SingleUserMall.Stores;
using SingleUserMall.Workers;
//using SingleUserMall.Workers.VO;

namespace SingleUserMall.Orders
{
    [AbpAuthorize]
    public class OrderManageAppService : SingleUserMallAppServiceBase, IOrderManageAppService
    {
        private readonly IRepository<Order, long> _orderRepository;
        private readonly IRepository<OrderDetail, long> _orderDetailRepository;
        private readonly IRepository<Store> _storeRepository;
        private readonly IRepository<UserAddress, long> _userAddressRepository;
        private readonly IRepository<Coupon, long> _couponRepository;
        public OrderManageAppService(
            IRepository<Order, long> orderRepository,
            IRepository<UserAddress, long> userAddressRepository,
            IRepository<Coupon, long> couponRepository,
            IRepository<Store> storeRepository,
            IRepository<OrderDetail, long> orderDetailRepository
            )
        {
            _orderDetailRepository = orderDetailRepository;
            _orderRepository = orderRepository;
            _userAddressRepository = userAddressRepository;
            _couponRepository = couponRepository;
            _storeRepository = storeRepository;
        }
        public async Task<OrderVO> GetOrderAsync(SingleId<long> form)
        {
            var userId = AbpSession.GetUserId();
            bool isAdmin = await UserManager.CheckAdminAndPlatformRole(userId);
            var storeId = _storeRepository.FirstOrDefault(x => x.UserId == userId).Id;
            var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
            var user = await UserManager.FindByIdAsync(order.UserId);
            return order.ToVO<Order, OrderVO>((o, vo) =>
            {
                if (o.MinTreeNumber != null)
                {
                    vo.TreeNumberRange = (o.MinTreeNumber == o.MaxTreeNumber) ? o.MinTreeNumber : o.MinTreeNumber + "~" + o.MaxTreeNumber;
                }
                vo.OrderDetails = o.OrderDetails.Where(x=> x.IsRefund == false).ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                {
                    var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                    dvo.inItem = itemSpec.Item;
                    dvo.inItemSpec = itemSpec;
                });
                // vo.WorkerView = o.Worker.ToVO<Worker, WorkerViewVO>();
            });
        }



        public async Task<PagedResultDto<OrderMiniVO>> GetOrdersAsync(OrderSearchForm form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                IQueryable<Order> query = _orderRepository.GetAll().Where(x => x.ShoppingCartType == ShoppingCarts.ShoppingCartType.ShoppingItems)
             .WhereIf(!string.IsNullOrEmpty(form.ShippingNo), x => x.ShippingNo.Contains(form.ShippingNo))
             .WhereIf(!string.IsNullOrEmpty(form.ReceiverPhone), x => x.ReceiverPhone.Contains(form.ReceiverPhone))
             .WhereIf(!string.IsNullOrEmpty(form.OrderNo), x => x.OrderNo.Contains(form.OrderNo))
             .WhereIf(form.BeginTime.HasValue, x => DbFunctions.TruncateTime(x.PayTime) >= DbFunctions.TruncateTime(form.BeginTime))
             .WhereIf(form.EndTime.HasValue, x => DbFunctions.TruncateTime(x.PayTime) <= DbFunctions.TruncateTime(form.EndTime))
             .WhereIf(form.Status.HasValue && form.Status != OrderStatus.Paid, x => x.Status == form.Status)
             .WhereIf(!form.Status.HasValue, x => x.Status >= OrderStatus.WaitPay)
             .WhereIf(form.Status.HasValue && form.Status == OrderStatus.Paid, x =>  (x.Status == OrderStatus.Paid && !x.IsGroup) || (x.Status == OrderStatus.Group && x.IsGroup))
             .WhereIf(form.PayType.HasValue, x => x.PayType == form.PayType)
             .OrderByDescending(x => x.CreationTime);
                if (form.StoreId.HasValue)
                {
                    query = (from s in query
                             join b in _orderDetailRepository.GetAll() on s.Id equals b.OrderId
                             where b.ItemSpec.Item.StoreId == form.StoreId
                             select s).OrderByDescending(x => x.CreationTime);
                }
                return await query.ToPagedResultDtoAsync<Order, OrderMiniVO>(form, (o, vo) =>
                {
                    vo.OrderDetails = o.OrderDetails.Where(x=> x.IsRefund == false).WhereIf(form.StoreId.HasValue, x => x.ItemSpec.Item.StoreId == form.StoreId).ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                    {
                        var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                        dvo.inItem = itemSpec.Item;
                        dvo.inItemSpec = itemSpec;
                    });
                    vo.BuyUserPhone = o.User.PhoneNumber;
                });
            }
        }
        public async Task<PagedResultDto<OrderDividendMiniVO>> GetTreeOrdersAsync(OrderSearchForm form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                IQueryable<Order> query = _orderRepository.GetAll().Where(x => x.ShoppingCartType==ShoppingCarts.ShoppingCartType.TreeShopping)
             .WhereIf(!string.IsNullOrEmpty(form.ShippingNo), x => x.ShippingNo.Contains(form.ShippingNo))
             .WhereIf(!string.IsNullOrEmpty(form.ReceiverPhone), x => x.ReceiverPhone.Contains(form.ReceiverPhone))
             .WhereIf(!string.IsNullOrEmpty(form.OrderNo), x => x.OrderNo.Contains(form.OrderNo))
             .WhereIf(form.BeginTime.HasValue, x => DbFunctions.TruncateTime(x.PayTime) >= DbFunctions.TruncateTime(form.BeginTime))
             .WhereIf(form.EndTime.HasValue, x => DbFunctions.TruncateTime(x.PayTime) <= DbFunctions.TruncateTime(form.EndTime))
             .WhereIf(form.Status.HasValue, x => x.Status == form.Status)
             .WhereIf(form.PayType.HasValue, x => x.PayType == form.PayType)
             .OrderByDescending(x => x.CreationTime);
                if (form.StoreId.HasValue)
                {
                    query = (from s in query
                             join b in _orderDetailRepository.GetAll() on s.Id equals b.OrderId
                             where b.ItemSpec.Item.StoreId == form.StoreId
                             select s).OrderByDescending(x => x.CreationTime);
                }
                return await query.ToPagedResultDtoAsync<Order, OrderDividendMiniVO>(form, (o, vo) =>
                {
                    vo.OrderDetails = o.OrderDetails.WhereIf(form.StoreId.HasValue, x => x.ItemSpec.Item.StoreId == form.StoreId).ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                    {
                        var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                        dvo.inItem = itemSpec.Item;
                        dvo.inItemSpec = itemSpec;
                        dvo.DividendAmountView = ((int)(dvo.DividendAmount * 100)).ToString();
                        if (dvo.Timelimit > 0)
                        {
                            dvo.DividendAmountViewByYear = ((int)(dvo.DividendAmount * 100 / dvo.Timelimit * 12)).ToString();
                        }
                    });
                    vo.Purchaser = o.User.Name;
                    vo.PurchaserPhone = o.User.PhoneNumber;
                });
            }
        }

        public async Task SetOrderReceivedAsync(SingleId<long> form)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
            order.Status = OrderStatus.Successed;
            order.ReceiveTime = DateTime.Now;
            order.OrderDetails.ToList().ForEach((x =>
            {
                var store = _storeRepository.FirstOrDefault((Store y) => y.Id == x.ItemSpec.Item.StoreId);
                store.SaleAmount += x.Price * x.Qty;
                store.UnBanlancedSaleAmount += x.Price * x.Qty;
            }));
        }

        public async Task SetOrderSentAsync(OrderSentForm form)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
            order.Status = OrderStatus.Sent;
            order.ShippingNo = form.ShippingNo;
            order.ShippingTime = DateTime.Now;
        }
    }
}
